#import "wooddoc.h"

@implementation WoodDoc (SearchableText)

- (oneway void)makeSelectionVisible
{
	NXRect scrollRect;
	
	if(lastSelectedNode){
		[window disableFlushWindow];
		[lastSelectedNode getBounds:&scrollRect];
		[treeView scrollRectToVisible:&scrollRect];
		[window reenableFlushWindow];
		[window flushWindow];
	}
}

- (int)replaceAll:(const char *)pattern with:(const char *)replacement 
  mode:(SearchMode)mode regexpr:(BOOL)regexpr cases:(BOOL)cases
{
	id searchTree, searchEndTree;
	int result;

	switch(mode){
		case SelStartToSelEnd:
			if(lastSelectedNode){
				searchTree = lastSelectedNode;
				searchEndTree = [lastSelectedNode lastInDepth];
			} else {
				searchTree = tree;
				searchEndTree = [tree lastInDepth];
			}
			break;
		case TextEdgeToTextEdge:
			searchTree = tree;
			searchEndTree = [tree lastInDepth];
			break;							
		default:
			return SEARCH_INVALID_ARGUMENT;
	}
	result = 0;
	[searchTree replaceTreeFor:pattern with:replacement untilNode:searchEndTree
	 regexpr:regexpr cases:cases result:&result];
	if(result > 0)
		[self updateViewsDirty:YES rect:NULL flag:(UPDATE_TREEVIEW | CHECK_RESIZE)]; 
	return result;
}
				
- (oneway void)replaceSelection:(const char *)replacement
{
	if(lastSelectedNode){
		if([lastSelectedNode replaceLabelSelectionWith:replacement pos:findPos size:findSize])
			[self updateViewsDirty:YES rect:NULL flag:(UPDATE_TREEVIEW | CHECK_RESIZE)];
	}
	return;
}

- (int)searchFor:(const char *)pattern mode:(SearchMode)mode 
  reverse:(BOOL)rev regexpr:(BOOL)regexpr cases:(BOOL)cases position:(out int *)pos size:(out int *)size
{
	id searchTree, searchEndTree;
	
	findSelectedNode = nil;
	findPos = 0; findSize = 0;
	switch(mode){
		case SelStartToSelEnd:
			if(lastSelectedNode){
				searchTree = [lastSelectedNode previousInDepth];
				searchEndTree = [lastSelectedNode nextInDepth];
			} else {
				searchTree = [tree previousInDepth];
				searchEndTree = tree;
			}
			break;
		case SelEndToSelStart:
			if(!lastSelectedNode){
				searchTree = tree;
				searchEndTree = [tree lastInDepth];
			} else {
				searchTree = [lastSelectedNode nextInDepth]; 
				searchEndTree = [lastSelectedNode previousInDepth];
			}
			break;							
		default:
			return SEARCH_INVALID_ARGUMENT;
	}
	findSelectedNode = [searchTree searchTreeFor:pattern untilNode:searchEndTree
						reverse:rev regexpr:regexpr cases:cases position:pos size:size];
	if(findSelectedNode){
		findPos = *pos;
		findSize = *size;
	} 
	return (findSelectedNode == nil ? 0 : 1);
}

- (oneway void)selectTextFrom:(int)start to:(int)end
{	
	if(findSelectedNode){
		[self declareSelection:findSelectedNode];
		[self updateViewsDirty:NO rect:NULL flag:UPDATE_TREEVIEW];
		findSelectedNode = nil;
	}
}

- (void)writeSelectionToPasteboard:(in Pasteboard *)pboard asType:(in NXAtom)type;
{
	int len;
	
	if(lastSelectedNode){
		len = strlen([lastSelectedNode label]);
		if(len){
      		[pboard declareTypes:&type num:1 owner:NULL];
      		[pboard writeType:type data:[lastSelectedNode label] length:len];
    	}
	}
}

@end

